package com.logic
{
	import com.action.ActionAttack;
	import com.action.ActionBullet;
	import com.action.ActionHurt;
	import com.action.ActionMove;
	import com.keyboard.KeyboardManager;
	import com.net.udp.UDPServer;
	import com.resource.animation.Animation;
	import com.resource.animation.AnimationCacher;
	import com.resource.unit.ActionUnit;
	import com.stage.item.BasePlayer;
	import com.stage.item.Player;
	
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	
	import mx.core.Application;

	public class BattleLogic
	{
		public static var hostId:String; // 战斗时的主机id
		public static var team1:Array; // 主队，相对的，如果是是当前客户端所在的队伍则为主队
		public static var team2:Array; // 客队
		public static var bullet1:Array; // 主队释放的子弹
		public static var bullet2:Array; // 客队释放的子弹
		public static var playerList:Object = {};
		public static var thisPlayer:Player;
		
		public static var bulletIdNum:int = 0;
		public static var bulletList:Object = {};
		
		public static var keyPressed:Object = {};
		
		public static var aid:String; // 当前客户端角色aid，临时
		
		public static var hurtList:Object = {}; // 适当的注意受伤间隔
		public static var minHurtDelay:int = 300;
		/**
		 * 初始化战斗场景，服务端推送战斗信息
		 */
		public static function onBattleInfo(host:String, info:Object):void{
			aid = Application.application.userName.text;
			hostId = host;
			
			var container:Sprite = Application.application.container;
			container.graphics.lineStyle(1, 0xff00ff);
			container.graphics.moveTo(200, 0);
			container.graphics.lineTo(200, 500);
			container.graphics.moveTo(0, 400);
			container.graphics.lineTo(600, 400);
			
			var t1:Array = info.team1;
			for(var i:int=0; i<t1.length; i++){
				var player:Player = new Player(t1[i], Application.application.container);
				player.x = 200;
				player.y = 400;
				playerList[player.data.aid] = player;
				player.play();
				player.visible = true; // 不可缺少的显示角色的两步
				player.act = ActionUnit.STAND;
				if(t1[i].aid == aid){
					team1 = info.team1;
					team2 = info.team2;
					thisPlayer = player;
				}
			}
			
			var t2:Array = info.team2;
			for(var i:int=0; i<t2.length; i++){
				var player:Player = new Player(t2[i], Application.application.container);
				player.x = 400;
				player.y = 400;
				playerList[player.data.aid] = player;
				player.play();
				player.visible = true; // 不可缺少的显示角色的两步
				player.act = ActionUnit.STAND;
				if(t2[i].aid == aid){
					team1 = info.team2;
					team2 = info.team1;
					thisPlayer = player;
				}
			}
			
			if(thisPlayer){
				var keyboard:KeyboardManager = 	KeyboardManager.getInstance();
				keyboard.setFuncCode(Keyboard.LEFT, moveLeftDown);
				keyboard.setFuncCode(Keyboard.RIGHT, moveRightDown);
				keyboard.setFuncCodeUp(Keyboard.LEFT, moveLeftUp);
				keyboard.setFuncCodeUp(Keyboard.RIGHT, moveRightUp);
				keyboard.setFunc("a", attackDown);
				keyboard.setFunc("s", skillDown);
				
				// 注意：
				// 主机战斗中用到的资源需要预加载
				var animaCacher:AnimationCacher = AnimationCacher.getInstance();
				animaCacher.load("res/bullet.dat");	
			}
		}
		
		/**
		 * 战斗结束，服务端返回战斗结果
		 */
		public static function onBattleEnd(res:Object):void{
			thisPlayer = null;
			var keyboard:KeyboardManager = 	KeyboardManager.getInstance();
			keyboard.setFuncCode(Keyboard.LEFT, null);
			keyboard.setFuncCode(Keyboard.RIGHT, null);
			keyboard.setFuncCodeUp(Keyboard.LEFT, null);
			keyboard.setFuncCodeUp(Keyboard.RIGHT, null);
			keyboard.setFunc("a", null);
			keyboard.setFunc("s", null);
		}
				
		/**
		 * 主机掉线等情况下更换主机
		 */
		public static function onChangeHost(newId:String):void{
			hostId = newId;
		}
		
		/**
		 * 战场中的移动
		 */
		public static function onBattleMove(aid:String, dir:int, speed:Number = -1):void{
			if(speed < 0){
				speed = BasePlayer.WALK_SPEED;
			}
			
			var player:Player = playerList[aid];
			if(player){
				if(dir == BasePlayer.WALK_DIR_NONE){
					if(player.action is ActionMove){
						player.action = null;
					}
//					player.walkStop();
				}else{
					if(player.action is ActionMove){
						(player.action as ActionMove).dir = dir;
						(player.action as ActionMove).speed = speed;
					}else{
						var action:ActionMove = new ActionMove(player, speed);
						player.action = action;
						action.start(dir);
					}
//					player.walkDir(dir, speed);
				}
			}
		}
		
		/**
		 * 攻击，包括攻击前摇，收手动作，施法中途可能被打断，可能释放出会移动或不移动或形变的子弹
		 * 是被检测碰撞对象
		 */
		public static function onAttack(aid:String, skillId:String, dir:int):void{
			var player:Player = playerList[aid];
			if(player){
				var action:ActionAttack = new ActionAttack(player, skillId);
				player.action = action;
				action.start(dir);
			}
		}
		
		/**
		 * 子弹，包括一切有攻击效果的动画，如子弹，炸弹，地上出现的持续性特效等
		 * 是检测碰撞对象
		 * 注意：这里没有把位置信息传过来
		 */
		public static function onBullet(aid:String, skillId:String, bulletId:int, dir:int, x:Number, y:Number):void{
			var player:Player = playerList[aid];
			if(player){
				var action:ActionBullet = new ActionBullet(player, skillId, bulletId, dir, x, y);
				bulletList[action.bulletId] = action;
				action.start();
			}
		}
		
		/**
		 * 击中，包括被攻击动画和子弹动画击中，
		 * 是被检测碰撞对象
		 */
		public static function onHurt(selfId:String, targetId:String, skillId:String, dir:int, hp:int, bulletId:int):void{
			var selfObj:Player = playerList[selfId];
			var targetObj:Player = playerList[targetId];
			if(targetObj){
				if(targetObj.action is ActionHurt){
					targetObj.action.start(dir);
				}else{
					var action:ActionHurt = new ActionHurt(targetObj);
					targetObj.action = action;
					action.start(dir);
				}
			}
			var bullet:ActionBullet = bulletList[bulletId];
			if(bullet){
				delete bulletList[bulletId];
				bullet.end();
			}
		}
		/**********************************************************************************************
		 * 一些基本操作
		 ***********************************************************************************************/
		public static function sendBullet(aid:String, skillId:String, dir:int, x:Number, y:Number):void{
			bulletIdNum++;
			UDPServer.getInstance().battleGroup.broadcast("onBullet", aid, skillId, bulletIdNum, dir, x, y);
		}
		
		public static function hitTest(obj1:Object, obj2:Object):Boolean{
			if(obj1.x1 > obj2.x2 || obj1.x2 < obj2.x1 || obj1.y1 > obj2.y2 || obj1.y2 < obj2.y1){
				return false;
			}
			return true;
		}
		
		/**
		 * 子弹打中人
		 */
		public static function bulletHitPlayer(bullet:ActionBullet):void{
			var team:Array = inTeam(bullet.player.data.aid, team1) ? team2 : team1;
			var attRect:Object = bullet.animation.attRect;
			var now:Number = (new Date).time;
			if(attRect && attRect.x1 < attRect.x2){
				var position:Point = bullet.animation.position;
				var attObj:Object = {
					x1 : bullet.animation.x + (attRect.x1 - position.x) * bullet.dir,
					y1 : bullet.animation.y + attRect.y1 - position.y,
					x2 : bullet.animation.x + (attRect.x2 - position.x) * bullet.dir,
					y2 : bullet.animation.y + attRect.y2 - position.y
				};
				if(attObj.x1 > attObj.x2){
					var a:Number = attObj.x2;
					attObj.x2 = attObj.x1;
					attObj.x1 = a;
				}
				if(team){
					for(var i:int=0; i<team.length; i++){
						if(team[i]){
							var player:Player = playerList[team[i].aid];
							if(player && (!hurtList[player.data.aid] || now - hurtList[player.data.aid] >= minHurtDelay)){
								var hitRect:Object = player.view.getHitRect();
								if(hitRect){
									var pos:Point = player.view.getPosition();
									var hitObj:Object = {
										x1 : player.x + (hitRect.x1 - pos.x) * player.dir,
										y1 : player.y + hitRect.y1 - pos.y,
										x2 : player.x + (hitRect.x2 - pos.x) * player.dir,
										y2 : player.y + hitRect.y2 - pos.y
									};
									if(hitRect.x1 > hitRect.x2){
										var a:Number = hitRect.x2;
										hitRect.x2 = hitRect.x1;
										hitRect.x1 = a;
									} 
									if(hitTest(attObj, hitObj)){
										// 击中
										hurtList[player.data.aid] = now;
										UDPServer.getInstance().battleGroup.broadcast("onHurt", bullet.player.data.aid, player.data.aid, bullet.skillId, bullet.dir, 100, bullet.bulletId);
									}
								}
							}
						}
					}
				}
			}
		}
		
		/**
		 * 人打中人
		 */
		public static function playerHitPlayer(action:ActionAttack):void{
			var selfPlayer:Player = action.player;
			var skillId:String = action.skillId;
			var team:Array = inTeam(selfPlayer.data.aid, team1) ? team2 : team1;
			var attRect:Object = selfPlayer.view.getAttRect();
			var now:Number = (new Date).time;
			if(attRect && attRect.x1 < attRect.x2){
				var position:Point = selfPlayer.view.getPosition();
				var attObj:Object = {
					x1 : selfPlayer.x + (attRect.x1 - position.x) * action.dir,
					y1 : selfPlayer.y + attRect.y1 - position.y,
					x2 : selfPlayer.x + (attRect.x2 - position.x) * action.dir,
					y2 : selfPlayer.y + attRect.y2 - position.y
				};
				if(attObj.x1 > attObj.x2){
					var a:Number = attObj.x2;
					attObj.x2 = attObj.x1;
					attObj.x1 = a;
				}
				if(team){
					for(var i:int=0; i<team.length; i++){
						if(team[i]){
							var player:Player = playerList[team[i].aid];
							if(player && (!hurtList[player.data.aid] || now - hurtList[player.data.aid] >= minHurtDelay)){
								var hitRect:Object = player.view.getHitRect();
								if(hitRect){
									var pos:Point = player.view.getPosition();
									var hitObj:Object = {
										x1 : player.x + (hitRect.x1 - pos.x) * player.dir,
										y1 : player.y + hitRect.y1 - pos.y,
										x2 : player.x + (hitRect.x2 - pos.x) * player.dir,
										y2 : player.y + hitRect.y2 - pos.y
									};
									if(hitRect.x1 > hitRect.x2){
										var a:Number = hitRect.x2;
										hitRect.x2 = hitRect.x1;
										hitRect.x1 = a;
									} 
									if(hitTest(attObj, hitObj)){
										hurtList[player.data.aid] = now;
										UDPServer.getInstance().battleGroup.broadcast("onHurt", selfPlayer.data.aid, player.data.aid, skillId, action.dir, 100, 0);
									}
								}
							}
						}
					}
				}
			}
		}
		
		/**
		 * 人撞上子弹
		 */
		public static function playerComeBullet(player:Player):void{
			
		}
		
		/**
		 * 人撞上人
		 */
		public static function playerComePlayer(player:Player):void{
			
		}
		
		public static function inTeam(aid:String, team:Array):Boolean{
			for(var i:int=0; i<team.length; i++){
				if(team[i] && team[i].aid==aid){
					return true;	
				}
			}
			return false;
		}
		/**********************************************************************************************
		 * 主机函数，只有被选为主机才能够接收消息
		 * 
		 * 技能使用时，必须先到主机请求
		 * 发出子弹，击中目标由主机进行判断发出消息，非主机客户端不作子弹发出和击中目标的判断
		 * 注意：战斗中移动目前直接由各自客户端向其他客户端发出，如果对同步影响过大需要改为主机请求方式
		 *********************************************************************************************/
		
		/**
		 * 某个角色使用技能必须先到主机请求 
		 */
		public static function onAttackServer(aid:String, skillId:String, dir:int):void{
			if(hostId != aid){
				return;
			}
			var player:Player = playerList[aid];
			if(player){
				if(player.action is ActionAttack || player.action is ActionHurt){
					return;
				}else{
					// 通过服务端验证，向普通客户端广播
					UDPServer.getInstance().battleGroup.broadcast("onAttack", aid, skillId, dir);
				}
			}
		}
		/***********************************************************************************
		 * 热键操作
		 ************************************************************************************/
		public static function moveLeftDown():void{
			if(keyPressed[Keyboard.LEFT]){
				
			}else{
				keyPressed[Keyboard.LEFT] = true;
				UDPServer.getInstance().battleGroup.broadcast("onBattleMove", thisPlayer.data.aid, BasePlayer.WALK_DIR_LEFT);
			}
		}
		
		public static function moveRightDown():void{
			if(keyPressed[Keyboard.RIGHT]){
				
			}else{
				keyPressed[Keyboard.RIGHT] = true;
				UDPServer.getInstance().battleGroup.broadcast("onBattleMove", thisPlayer.data.aid, BasePlayer.WALK_DIR_RIGHT);
			}
		}
		
		public static function moveLeftUp():void{
			delete keyPressed[Keyboard.LEFT];
			UDPServer.getInstance().battleGroup.broadcast("onBattleMove", thisPlayer.data.aid, BasePlayer.WALK_DIR_NONE);
		}
		
		public static function moveRightUp():void{
			delete keyPressed[Keyboard.RIGHT];
			UDPServer.getInstance().battleGroup.broadcast("onBattleMove", thisPlayer.data.aid, BasePlayer.WALK_DIR_NONE);
		}
		
		public static function attackDown():void{
			UDPServer.getInstance().battleGroup.broadcast("onAttackServer", thisPlayer.data.aid, "attack", thisPlayer.dir);
		}
		
		public static function skillDown():void{
			UDPServer.getInstance().battleGroup.broadcast("onAttackServer", thisPlayer.data.aid, "skill", thisPlayer.dir); 
		}
	}
}